/* Author: YangSaqing
 * Last edit:2019-03-07
 *
 */

#ifndef PDXP_H
#define PDXP_H
#include <QUdpSocket>
#include <cstring>
class Pdxp;
/*
 * info: PDXP协议帧头类,包含帧头各字段定义.
*/
class PdxpHead{
    friend class Pdxp;
public:
    PdxpHead()
    {
        memset(mHeader,0,32);
    }
    /*
     * @brief: 枚举类型,字段的值为相对帧头起始的字节偏移量.
     */
    enum HeadFlag{VER = 0,
                 MID = 1,
                 SID = 3,
                 DID = 7,
                 BID = 11,
                 No = 15,
                 FLAG = 19,
                 Reserve = 20,
                 DATE = 24,
                 TIME = 26,
                 Length = 30};

    /*
     * @brief: 返回帧头某个字段的值.
     * @arg: opt为字段名.
     * @return: 以无符号整数方式返回字段的值.
     */
    unsigned int getOpt(HeadFlag opt) const;

    /*
     * @brief: 设置帧头某个字段的值.
     * @arg: opt为字段名, value为字段的值.
     */
    void setOpt(HeadFlag opt, const unsigned int &value);

    //以字符串形式返回帧头数据的概要信息
    QString inf()const;

    //返回帧头的起始地址,即mHeader的值.
    char* data();
private:
    //以PDXP帧头格式存储PDXP帧头数据.
    char mHeader[32];
};

/*
 * info: 继承自QUdpSocket类,封装PDXP协议格式
 */
class Pdxp:public QUdpSocket
{
    Q_OBJECT
public:
    explicit Pdxp(QObject *parent = Q_NULLPTR);
    virtual ~Pdxp();

    /*
     * @brief: 发送一个PDXP格式的数据帧.
     * @arg: head 要发送的PDXP帧头;
     *       data 要发送的PDXP数据段指针;
     *       add 目的IP地址;
     *       port 目的端口;
     * @return: 若发送成功,则返回true,否则返回false.
     */
    virtual bool sendPdxp(PdxpHead &head, const char *data, const QHostAddress &add, const quint16 &port);

    /*
     * @brief: 读取一个PDXP帧,读取的信息在于head,data,addr,port中.
     * @arg: head 存放读取的PDXP帧的帧头数据;
     *       data 存放读取的PDXP数据段的数据;
     *       maxLength data的最大长度;
     *       addr 接收到的数据的源IP地址;
     *       port 接收到的数据源端口.
     * @return: PDXP数据段的长度.
     */
    virtual int readPdxp(PdxpHead *head, char *data, const unsigned int &maxLength, QHostAddress *addr, quint16 *port);//return data's real length
};
#endif // PDXP_H
